﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SharePointUtilitiesForDevelopers.Action
{
    /// <summary>
    /// An action plug-in loader that gets the actions from the file system.
    /// </summary>
    public class FileSystemActionLoader: IActionLoader
    {
        private readonly string _actionsDirectory;

        /// <summary>
        /// Initializes a new instance of the <see cref="FileSystemActionLoader"/> class.
        /// </summary>
        public FileSystemActionLoader()
        {
            _actionsDirectory = AppDomain.CurrentDomain.BaseDirectory;    
        }

        /// <summary>
        /// Loads the actions from the file system.
        /// </summary>
        /// <param name="manager">The manager.</param>
        public void Load(IActionManager manager)
        {
            // Get assembly files
            var fileNames = Directory.GetFiles(
                _actionsDirectory).ToList().Where(f => Path.GetExtension(f) == ".dll" || Path.GetExtension(f) == ".exe");
            
            // Load each assembly
            foreach (var fileName in fileNames)
            {
                LoadActionAssembly(fileName, manager);
            }
        }

        /// <summary>
        /// Loads an action assembly.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="manager">The manager.</param>
        private static void LoadActionAssembly(string fileName, IActionManager manager)
        {
            // Load the assembly
            var assembly = Assembly.LoadFile(fileName);
            
            // Get all action classes in the assembly
            var types = assembly.GetTypes().ToList().Where(t => t.IsClass && typeof(IAction).IsAssignableFrom(t));

            // Enumerate each type and determine if it's an action
            foreach (var type in types)
            {
                // Create instance
                var action = (IAction)ServiceLocator.Container.Resolve(type);

                // Add the action
                manager.AddAction(action);

            }
        }
    }
}
